/**********************************************************************************
 * Code license:  GNU General Public License v3                                   *
 * Main page:     https://code.google.com/p/library-cross-platform/               *
 * Issue tracker: https://code.google.com/p/library-cross-platform/issues/list    *
***********************************************************************************/

package library.util.resources;

import java.io.*;
import java.util.*;
import java.util.zip.*;

@SuppressWarnings({"rawtypes", "unchecked"})
public class ZipResourcesLoader implements ResourcesLoader {

  protected String            fileName;
  protected Hashtable         sizesTable        = new Hashtable();
  protected Hashtable         zipContentsTable  = new Hashtable();
  
  private FileInputStream     fis;
  private BufferedInputStream bis;
  private ZipInputStream      zis;
  private ZipEntry            ze;

  public ZipResourcesLoader() {
  }

  public ZipResourcesLoader(String file) {
    setFileName(file);
  }

  public void setFileName(String file) {
    fileName = file;
  }
  
  public final String getFileName() {
    return fileName;
  }
  
  public byte[] getResource(String name) {
    return (byte[]) zipContentsTable.get(name);
  }
  
  public List getContent() {
    List retData = new ArrayList();
    Enumeration e = zipContentsTable.keys();
    while(e.hasMoreElements()) {
      retData.add(e.nextElement());
    }
    return retData;    
  }
  
  protected boolean checkFileExtension(String name) {
    return true;
  }
  
  public void load() throws NullPointerException, FileNotFoundException, IOException {
    byte[] byte_data  = null;
    int read_bytes    = 0;
    int read_size     = 0;
	  
/* get names and sizes */
    ZipFile zf = new ZipFile(fileName);
    Enumeration e = zf.entries();
    while (e.hasMoreElements()) {
      ZipEntry ze = (ZipEntry) e.nextElement();
      sizesTable.put(ze.getName(), new Integer((int) ze.getSize()));
    }
    zf.close();

/* load resources */
    fis = new FileInputStream(fileName);
    bis = new BufferedInputStream(fis);
    zis = new ZipInputStream(bis);
    ze  = null;
    while ((ze = zis.getNextEntry()) != null) {
      if (ze.isDirectory())
        continue;
      else if(checkFileExtension(ze.getName()) == false)
        continue;

      int size = (int) ze.getSize(); //the uncompressed size of the entry data, or -1 if not known
      if (size == -1)
        size = ((Integer) sizesTable.get(ze.getName())).intValue();

      byte_data = new byte[size];
      read_bytes = 0;
      read_size = 0;
      while ((size - read_bytes) > 0) {
        read_size = zis.read(byte_data, read_bytes, size - read_bytes);
        if (read_size == -1)
          break;
        read_bytes += read_size;
      }
/* add to hashtable */
      zipContentsTable.put(ze.getName(), byte_data);
    }
  }

}
